/*
 * $Id: sysapi.h,v 1.56 2006-03-21 16:15:16 bacon Exp $
 */

#ifndef _XP_BAS_SYSAPI_H_
#define _XP_BAS_SYSAPI_H_

#include <xp/types.h>
#include <xp/macros.h>
#include <xp/bas/time.h>

#ifdef _WIN32
	#include <xp/bas/winapi.h>
#else
	#include <xp/bas/unxapi.h>
	/* TODO: remove this line after defining SEEK_SET, etc... */
	#include <unistd.h>
	#include <fcntl.h>
	#include <limits.h>
#endif

/* flags for xp_open */
enum
{
	XP_OPEN_READ      = (1 << 0),
	XP_OPEN_WRITE     = (1 << 1),
	XP_OPEN_CREATE    = (1 << 2),
	XP_OPEN_TRUNCATE  = (1 << 3),
	XP_OPEN_EXCLUSIVE = (1 << 4),
	XP_OPEN_APPEND    = (1 << 5),
	XP_OPEN_NONBLOCK  = (1 << 6)
};

/*
#define XP_OPEN_READ       O_RDONLY
#define XP_OPEN_WRITE      O_WRONLY
#define XP_OPEN_READ_WRITE O_RDWR
#define XP_OPEN_CREATE     O_CREAT
#define XP_OPEN_EXCLUSIVE  O_EXCL
#define XP_OPEN_NOCTTY     O_NOCTTY
#define XP_OPEN_TRUNCATE   O_TRUNC
#define XP_OPEN_APPEND     O_APPEND
#define XP_OPEN_NONBLOCK   O_NONBLOCK
#define XP_OPEN_SYNC       O_SYNC
#define XP_OPEN_NOFOLLOW   O_NOFOLLOW
#define XP_OPEN_DIRECTORY  O_DIRECTORY
#define XP_OPEN_DIRECT     O_DIRECT
#define XP_OPEN_ASYNC      O_ASYNC
#define XP_OPEN_LARGEFILE  O_LARGEFILE
*/

/* options for xp_access */
#ifdef _WIN32
	#define XP_ACCESS_READ    04
	#define XP_ACCESS_WRITE   02
	#define XP_ACCESS_EXECUTE 01 
	#define XP_ACCESS_EXIST   00
#else
	#define XP_ACCESS_READ    R_OK
	#define XP_ACCESS_WRITE   W_OK
	#define XP_ACCESS_EXECUTE X_OK
	#define XP_ACCESS_EXIST   F_OK
#endif

/* origin for xp_seek */
enum
{
	XP_SEEK_BEGIN   = 0,
	XP_SEEK_CURRENT = 1,
	XP_SEEK_END     = 2
};

/* poll interface */
#if defined(__linux) || !defined(XP_HAVE_POLL_H)
	enum
	{
		XP_POLLIN  = 0x0001,
		XP_POLLPRI = 0x0002, /* There is urgent data to read */
		XP_POLLOUT = 0x0004, /* Writing now will not block */
		XP_POLLERR = 0x0008, /* Error condition */
		XP_POLLHUP = 0x0010, /* Hung up */
		XP_POLLNVAL = 0x0020 /* Invalid request: fd not open */
	};

	typedef struct xp_poll_t xp_poll_t;

	struct xp_poll_t
	{
		int fd;
		short events;
		short revents;
	};

#else
	#include <poll.h>
	enum
	{
		XP_POLLIN  = POLLIN,
		XP_POLLPRI = POLLPRI,
		XP_POLLOUT = POLLOUT,
		XP_POLLERR = POLLERR,
		XP_POLLHUP = POLLHUP,
		XP_POLLNVAL = POLLNVAL
	};
	typedef struct pollfd xp_poll_t;
#endif

/* epoll interface */
#ifdef XP_HAVE_SYS_EPOLL_H
	#include <sys/epoll.h>
	enum
	{
		XP_EPOLLIN  = EPOLLIN,
		XP_EPOLLPRI = EPOLLPRI,
		XP_EPOLLOUT = EPOLLOUT,
		XP_EPOLLERR = EPOLLERR,
		XP_EPOLLHUP = EPOLLHUP
	};
#else
	enum
	{
		XP_EPOLLIN  = XP_POLLIN,
		XP_EPOLLPRI = XP_POLLPRI,
		XP_EPOLLOUT = XP_POLLOUT,
		XP_EPOLLERR = XP_POLLERR,
		XP_EPOLLHUP = XP_POLLHUP
	};
#endif

struct xp_epoll_event_t
{
	int events;
	int handle;
};
typedef struct xp_epoll_event_t xp_epoll_event_t;

struct xp_epoll_t
{
	xp_epoll_event_t* revents;
	xp_size_t __size;
	xp_size_t __capacity;

	xp_hnd_t __handle; 
	union {
#ifdef XP_HAVE_SYS_EPOLL_H
		struct epoll_event* ep;
#endif
		xp_poll_t* bp;
	} __events;

	xp_bool_t __dynamic;
};
typedef struct xp_epoll_t xp_epoll_t;

#ifdef __cplusplus
extern "C" {
#endif

xp_mode_t xp_umask (xp_mode_t mode);

/* handle io */
xp_hnd_t xp_open (const xp_char_t* path, int flag, ...);
xp_hnd_t xp_opentmp (xp_char_t* tmpl);

int xp_close (xp_hnd_t handle);
xp_ssize_t xp_read (xp_hnd_t handle, void* buf, xp_size_t sz);
xp_ssize_t xp_write (xp_hnd_t handle, const void* data, xp_size_t sz);
xp_off_t xp_seek (xp_hnd_t handle, xp_off_t offset, int origin);
int xp_hstat (xp_hnd_t handle, xp_stat_t* buf);
int xp_hchmod (xp_hnd_t handle, xp_mode_t mode);
int xp_htruncate (xp_hnd_t handle, xp_off_t size);

/* path operation */
int xp_stat (const xp_char_t* path, xp_stat_t* buf);
int xp_unlink (const xp_char_t* path);
int xp_rename (const xp_char_t* opath, const xp_char_t* npath);

int xp_access (const xp_char_t* path, int option);
int xp_chmod (const xp_char_t* path, xp_mode_t mode);
int xp_link (const xp_char_t* name1, const xp_char_t* name2);
int xp_symlink (const xp_char_t* name1, const xp_char_t* name2);
int xp_readlink (const xp_char_t* path, xp_char_t* buf, xp_size_t size);

int xp_getcwd (xp_char_t* buf, xp_size_t size);
int xp_mkdir (const xp_char_t* path, xp_mode_t mode);
int xp_rmdir (const xp_char_t* path);
int xp_chdir (const xp_char_t* path);

/*
 * FUNCTION: xp_trimpath
 *
 * PARAMETERS:
 *   src - [in] path name to trim
 *   dst - [in] pointer to the buffer to hold the result
 *   dstcnt - [in] size of *dst*  
 * 
 * RETURNS:
 *   Length of the trimmed path on success, (xp_size_t)-1 on failure
 * 
 * DESCRIPTION:
 *   When it fails, xp_errno is set to one of the following values 
 *   as well as (xp_size_t)-1 is returned.
 *     * XP_ENOMEM - it ran out of memory
 *     * XP_ENOSPC - *dst* is not large enough
 */
xp_size_t xp_trimpath (const xp_char_t* src, xp_char_t* dst, xp_size_t dstcnt);

/* 
 * FUNCTION: xp_getpnm
 *   Returns the path to the current process 
 */
int xp_getpnm (const xp_char_t* argv0, xp_char_t* buf, xp_size_t size);

/* poll interface */
xp_ssize_t xp_poll (xp_poll_t* fds, xp_size_t nfds, xp_time_t timeout);

/* epoll interface */
xp_epoll_t* xp_epoll_open (xp_epoll_t* p, xp_size_t size);
int xp_epoll_close (xp_epoll_t*);
int xp_epoll_add (xp_epoll_t* p, int fd, int events);
int xp_epoll_remove (xp_epoll_t* p, int fd, int events);
xp_ssize_t xp_epoll_wait (xp_epoll_t* p, xp_time_t timeout);

#ifdef __cplusplus
}
#endif

#endif

